using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Services;
using JigLibX.Physics;
using Utilities;
using WAS.Logic;
using WAS.Logic.SampleLevel;


namespace WAS
{
    using Nuke = Projectile;
    using NukeData = ProjectileData;

    public abstract class EffectsLayer : EnemiesLayer
    {
        List<Texture2D> testures;
        int textureCount;

        public EffectsLayer(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            textureCount = 0;
            testures = new List<Texture2D>();
        }

        //protected override void DrawPlayerWarp(State current_state, ModelWithVolumes Player)
        //{
        //    switch (current_state.player.warp_type)
        //    {
        //        case WarpType.Entering:
        //            if (player_warp_particle == null)
        //                player_warp_particle = effects.AddWarparticle(current_state.player.geometry.Position, 0.0f, Color.White);
        //            var warp_ratio = 1.0f - current_state.player.warping_in_timer / PlayerShip.WARP_TRANSITION_TIME;

        //            if (warp_ratio < 0.75f)
        //            {
        //                warp_ratio *= 4.0f / 3.0f;
        //                player_warp_particle.Position = current_state.player.geometry.Position +
        //                  warp_ratio * current_state.player.geometry.Orientation.Forward * Player.BoundingSphere.Radius * 0.75f;
        //                player_warp_particle.Size = MathHelper.SmoothStep(0.01f, 0.02f, warp_ratio) * 0.9f;
        //            }
        //            else
        //            {
        //                warp_ratio = (warp_ratio - 0.75f) * 4.0f;
        //                player_warp_particle.Position = current_state.player.geometry.Position +
        //                  (1.0f - warp_ratio) * current_state.player.geometry.Orientation.Forward * Player.BoundingSphere.Radius * 0.75f;
        //                player_warp_particle.Size = MathHelper.SmoothStep(0.02f, 0.05f, warp_ratio) * 0.9f;
        //            }
        //            break;
        //        case WarpType.Exiting:
        //            warp_ratio = 1.0f - current_state.player.warping_out_timer / PlayerShip.WARP_TRANSITION_TIME;
        //            if (warp_ratio > 0.75f)
        //            {
        //                warp_ratio = (warp_ratio - 0.75f) * 4.0f;
        //                player_warp_particle.Position = current_state.player.geometry.Position +
        //                  (1.0f - warp_ratio) * current_state.player.geometry.Orientation.Forward * Player.BoundingSphere.Radius * 0.75f;
        //                player_warp_particle.Size = MathHelper.SmoothStep(0.02f, 0.01f, warp_ratio) * 0.9f;
        //            }
        //            else
        //            {
        //                warp_ratio *= 4.0f / 3.0f;
        //                player_warp_particle.Position = current_state.player.geometry.Position +
        //                 warp_ratio * current_state.player.geometry.Orientation.Forward * Player.BoundingSphere.Radius * 0.75f;
        //                player_warp_particle.Size = MathHelper.SmoothStep(0.05f, 0.02f, warp_ratio) * 0.9f;
        //            }
        //            break;
        //        case WarpType.None:
        //            if (player_warp_particle != null)
        //            {
        //                player_warp_particle.IsActive = false;
        //                player_warp_particle = null;
        //            }
        //            break;
        //        default:
        //            break;
        //    }
        //}

        public struct genericExplosionInfo
        {
            public float age;
            public float size;
            public Vector3 position;
        }
        public static genericExplosionInfo gei;
        public static Action<WAS.EffectsManager.Explosion> init_ge = new Action<WAS.EffectsManager.Explosion>(p =>
        {
            p.age = gei.age;
            p.size = gei.size;
            p.position = gei.position;
        });

        protected override void DrawExplosions(ArrayList<Explosion> new_explosions)
        {
            //for_each (var explosion in new_explosions)
            for (int y = 0; y < new_explosions.Count; y++)
            {
                var explosion = new_explosions[y];
                var size_mult = (max_depth / (Vector3.Distance(EyePosition, Vector3.Zero) * 4.0f));

                switch (explosion.explosion_type)
                {
                    case ExplosionType.None:
                        break;
                    //case ExplosionType.Nuke:
                    //effects.AddExplosion(
                    //  new EffectsManager.Explosion()
                    //  {
                    //      age = 0.0f,
                    //      position = explosion.position,
                    //      size = explosion.originating_nuke.size * 0.1f * 0.2f * size_mult
                    //  });
                    case ExplosionType.Nuke:
                        gei = new genericExplosionInfo()
                        {
                            age = 0.0f,
                            position = explosion.position,
                            size = explosion.originating_nuke.size * 0.1f * 0.2f * size_mult
                        };
                        effects.AddExplosion(init_ge);

                        break;
                    //case ExplosionType.Ship:
                    //    var radius = explosion.originating_ship.geometry.CollisionSkin.WorldBoundingBox.Max.Y - explosion.originating_ship.geometry.CollisionSkin.WorldBoundingBox.Min.Y;
                    //    for (int i = 0; i < 3; i++)
                    //    {
                    //        effects.AddExplosion(exp
                    //          new EffectsManager.Explosion()
                    //          {
                    //              age = 0.0f,
                    //              position = explosion.position,
                    //              size = radius * 0.2f * 0.1f * size_mult * (i + 1) / 2.0f
                    //          });
                    //    }
                    //    break;
                    case ExplosionType.Ship:
                        var radius = explosion.originating_ship.geometry.CollisionSkin.WorldBoundingBox.Max.Y - explosion.originating_ship.geometry.CollisionSkin.WorldBoundingBox.Min.Y;
                        for (int i = 0; i < 3; i++)
                        {
                            gei = new genericExplosionInfo()
                            {
                                age = 0.0f,
                                position = explosion.position,
                                size = radius * 0.2f * 0.1f * size_mult * (i + 1) / 2.0f
                            };
                            effects.AddExplosion(init_ge);
                        }
                        break;
                    case ExplosionType.Laser:
                        gei = new genericExplosionInfo()
                            {
                                age = 0.0f,
                                position = explosion.position,
                                size = explosion.originating_laser.size * size_mult * 0.1f
                            };
                        effects.AddExplosion(init_ge);
                        break;
                    case ExplosionType.Asteroid:
                        gei = new genericExplosionInfo()
                            {
                                age = 0.0f,
                                position = explosion.position,
                                size = explosion.originating_asteroid.size * 0.1f * 0.2f * size_mult
                            };
                        effects.AddExplosion(init_ge);
                        break;
                    default:
                        break;
                }
            }
        }


        public static ShockWave sw_to_add;
        public Action<WAS.EffectsManager.ShockWave> init_sw = new Action<WAS.EffectsManager.ShockWave>(
            s =>
            {
                s.radius = 0.0f;
                s.position = sw_to_add.position;
                s.range = sw_to_add.range;
                s.initialColor = sw_to_add.initialColor;
                s.finalColor = sw_to_add.finalColor;
                s.speed = sw_to_add.speed;
            });

        protected override void DrawShockWaves(ArrayList<ShockWave> new_shockwaves)
        {
            //for_each (var sw in new_shockwaves)
            for (int i = 0; i < new_shockwaves.Count; i++)
            {
                sw_to_add = new_shockwaves[i];
                effects.AddShockWave(init_sw);
            }
        }
        
        protected override void DrawSlowMotionOverlay(State current_state)
        {

            var slow = current_state.slow_motion;
            if (slow < 1.0f)
            {
                float r = 0f;
                float g = 255f;
                float b = 0f;

                spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
                spriteBatch.Draw(white_pixel, new Rectangle(0, 0, GraphicsDevice.Viewport.Width,
                  GraphicsDevice.Viewport.Height), new Color(r, g, b, 0.7f - 0.7f * slow));
                spriteBatch.End();
            }
        }
        protected override void DrawAllertOverlay(State current_state)
        {
            //94.0f / 255.0f, 38.0f / 255.0f, 18.0f / 255.0f
            var allert = current_state.allert_motion;
            if (allert < 1.0f)
            {
                float r = 94.0f / 255.0f;
                float g = 38.0f / 255.0f;
                float b = 18.0f / 255.0f;
                
                spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
                spriteBatch.Draw(white_pixel, new Rectangle(0, 0, GraphicsDevice.Viewport.Width,
                  GraphicsDevice.Viewport.Height), new Color(r, g, b, 0.7f - 0.7f * allert));
                spriteBatch.End();
            }
        }
        
        protected override void DrawBuzzOverlay(State current_state)
        {
            //94.0f / 255.0f, 38.0f / 255.0f, 18.0f / 255.0f

            textureCount = textureCount % 3;

            var buzz = current_state.buzz_motion;
            if (buzz < 1.0f)
            {
                float r = 255f;
                float g = 255f;
                float b = 255f;

                var value = (float)Math.Max(0.0, 1 - (1.0f / (((State.MAX_BUZZ_MOTION_TIME - 1) * buzz) - State.MAX_BUZZ_MOTION_TIME) + 1.0f));

                spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
                spriteBatch.Draw(white_pixel, new Rectangle(0, 0, GraphicsDevice.Viewport.Width,
                  GraphicsDevice.Viewport.Height), new Color(r, g, b, 1.5f - 1.5f * value));
                spriteBatch.End();

            }
          ////  if (buzz <= 0 && state_provider.CurrentState.num_of_asteroids_hit <= 3)
          //  else
          //  {
          //      state_provider.CurrentState.num_of_asteroids_hit = 0;
          //  }
        }
    }
}
